import { twoline2satrec, propagate } from 'satellite.js';
import * as Cesium from 'cesium';

class SatelliteEntity {
	constructor(tle = '', options = {}) {
		const [name, tleLine1, tleLine2] = this._checkTle(tle);
		let meanMotion = parseFloat(tleLine2.slice(52, 63)); // 平均运动（每天转数）

		this.name = name.trim();
		this.tleLine1 = tleLine1.trim();
		this.tleLine2 = tleLine2.trim();
		this.satrec = twoline2satrec(this.tleLine1, this.tleLine2);

		// 支持动态设置预测时长，默认24小时
		this.totalSeconds = options.totalSeconds || 86400;
		this.stepSeconds = 100;

		// 计算轨道周期（秒）
		this.orbitalPeriod = (24 * 3600) / meanMotion; // 一个轨道周期的秒数

		// 轨道显示策略：从当前时间开始向前预测轨道
		// leadTime: 当前时刻向前显示的时间（秒）
		// trailTime: 当前时刻向后显示的时间（秒）
		// 向前和向后各显示1个轨道周期
		this.leadTime = this.orbitalPeriod * 1; // 向前显示1个轨道周期
		this.trailTime = this.orbitalPeriod * 1; // 向后显示1个轨道周期
	}

	_checkTle(tle) {
		let elements = tle.split('\n');
		if (elements.length !== 3) throw new Error('tle data error');
		return elements;
	}

	// 获取地心惯性坐标系坐标
	getPositionEci(time) {
		return propagate(this.satrec, time).position;
	}

	// 创建PositionProperty
	_getPositionProperty() {
		const start = Cesium.JulianDate.fromIso8601(new Date().toISOString());
		// 统一使用INERTIAL坐标系，让轨道在惯性空间中保持固定
		const positionProperty = new Cesium.SampledPositionProperty(Cesium.ReferenceFrame.INERTIAL);

		let now = Date.now();
		for (let i = 0; i < this.totalSeconds / this.stepSeconds; i++) {
			let sateTime = new Date(now + i * this.stepSeconds * 1000);
			let sateCoord = this.getPositionEci(sateTime);
			if (!sateCoord) continue;

			const cesiumTime = Cesium.JulianDate.addSeconds(start, i * this.stepSeconds, new Cesium.JulianDate());
			// 直接使用ECI坐标，在INERTIAL坐标系中显示
			const position = new Cesium.Cartesian3(sateCoord.x * 1000, sateCoord.y * 1000, sateCoord.z * 1000);

			positionProperty.addSample(cesiumTime, position);
		}
		return positionProperty;
	}

	// 创建卫星实例
	createSatelliteEntity() {
		const start = Cesium.JulianDate.fromIso8601(new Date().toISOString());
		const stop = Cesium.JulianDate.addSeconds(start, this.totalSeconds, new Cesium.JulianDate());
		const color = Cesium.Color.fromRandom({ alpha: 0.6 });
		let satelliteEntity = {
			name: this.name,
			description: this.name,
			availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: stop })]),
			position: this._getPositionProperty(),
			point: {
				pixelSize: 8,
				color: color
				// scaleByDistance: new Cesium.NearFarScalar(1.5e3, 1, 8.0e8, 0.5),
			},
			path: new Cesium.PathGraphics({
				width: 0.5,
				show: true,
				leadTime: this.leadTime,
				trailTime: this.trailTime,
				material: color
			}),
			label: {
				text: this.name,
				font: '12px sans-serif',
				showBackground: true,
				backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.5),
				backgroundPadding: new Cesium.Cartesian2(4, 4),
				outlineWidth: 1,
				verticalOrigin: Cesium.VerticalOrigin.TOP,
				horizontalOrigin: Cesium.VerticalOrigin.LEFT,
				pixelOffset: new Cesium.Cartesian2(0, 5),
				fillColor: Cesium.Color.WHITE
				// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 50000000),
			}
		};
		return satelliteEntity;
	}
}

export default SatelliteEntity;
